# Copyright (c) 2009 Olexandr Melnyk <me@omelnyk.net>
# See COPYING for details.

import re
import irclib

# Single-server translation bot for Internet Relay Chat
class Polybot:
    # Public constructor. The dicts argument must be an array of instances
    # of translator classes
    def __init__(self, dicts, logger, network, port, nick, name):
        # General options
        self._dicts = dicts
        self._logger = logger
        self.network = network
        self.port = port
        self.nick = nick
        self.name = name

        # Connection-related things
        self.irc = irclib.IRC()
        self.server = self.irc.server()
        self.server.connect(network, port, nick, name)

        # IRC event handlers
        self.irc.add_global_handler('pubmsg', getattr(self, '_on_chanmsg'))
        self.irc.add_global_handler('privmsg', getattr(self, '_on_privmsg'))

    # Join specified channel
    def join(self, channel):
        self.server.join(channel)

    # Send message to specified user or channel
    def send_msg(self, recepient, message):
        self.server.privmsg(recepient, message)

    # Generic message handler (respond_to must contain user or channel name,
    # to which bot should send its response)
    def _handle_msg(self, respond_to, message, sender):
        # If message is command, analyze it
        if re.match('![a-z]{2}-[a-z]{2}', message):
            self._logger.write ("%s: <%s> %s\n" % (respond_to, sender, message))
            cmd, message = message.split(' ', 1)
            source_lang, target_lang = cmd[1:].split('-')

            # Take into account optional dictionary list from the command
            if re.match('@[a-z]+', message):
                cmd_dicts_str, message = message[1:].split(' ', 1)
                cmd_dicts = req_dicts_str.split(",")
            else:
                cmd_dicts = None

            # Search word in dictionaries
            trans = []
            for d in self._dicts.values():
                if cmd_dicts == None or d.short_name in cmd_dicts:
                    if (source_lang, target_lang) in d.supported_pairs():
                        t = d.translate(message, source_lang, target_lang)
                        trans.extend(t)

            # Send response with translations
            response = message + ': '
            if trans:
                response += ', '.join(trans)
            else:
                response += 'No translations'
            self.send_msg(respond_to, response)

    # Private message handler
    def _on_privmsg(self, conn, event):
        sender = event.source().split('!')[0]
        message = event.arguments()[0]
        self._handle_msg(sender, message, sender)

    # Channel message handler
    def _on_chanmsg(self, conn, event):
        sender = event.source().split('!')[0]
        message = event.arguments()[0]
        channel = event.target()
        self._handle_msg(channel, message, sender)

    # Infinite event handling loop
    def event_loop(self):
        self.irc.process_forever()

